﻿#include "GameData.h"

CGameData g_GameData;

CGameData::CGameData()
{
	#define ADD_POINT_TO_LIST(a1, a2, a3) m_teleports.emplace_back(std::make_shared<STeleportPoint>(skCrypt(a1), a2, a3 ));
			ADD_POINT_TO_LIST("Kastleton", 0x15523809245ECAF8, false);
			ADD_POINT_TO_LIST("Golden Rye Pastures", 0x15523807245EC9C2, false);
			ADD_POINT_TO_LIST("Windhill Shores", 0x1552380B245EC9C3, false);
			ADD_POINT_TO_LIST("Blackhowl Plains", 0x15523801245EC9C1,false);
			ADD_POINT_TO_LIST("Urstella Fields", 0x15523804245EC9C2,false);
			ADD_POINT_TO_LIST("Starlight Observatory Ruins", 0x1552380F245ECAF9, true);
			ADD_POINT_TO_LIST("Carmine Forest", 0x15523800245EC9C1,false);
			ADD_POINT_TO_LIST("Nesting Grounds", 0x15A33813257F1EFC, false);
			ADD_POINT_TO_LIST("Vienta Village", 0x15523830245EC6EB,false);
			ADD_POINT_TO_LIST("Monolith Wastelands", 0x1552381A245EBCE2,false);
			ADD_POINT_TO_LIST("Titanreach Ruins", 0x15533913270BE61D, false);
			ADD_POINT_TO_LIST("Stonegard Castle", 0x15523837245EC6ED,false);
			ADD_POINT_TO_LIST("Abandoned Stonemason Town", 0x1552380E245EC5A3,false);
			ADD_POINT_TO_LIST("Sandworm Lair", 0X1552380C245EC5A5,false);
			ADD_POINT_TO_LIST("Moonlight Desert", 0x1552381B245EBCE2,false);
			ADD_POINT_TO_LIST("Sanctuary Oasis", 0x15523831245EC6ED,false);
			ADD_POINT_TO_LIST("Daybreak Shore", 0x15523815245EBCE1,false);
			ADD_POINT_TO_LIST("The Raging Wilds", 0x15523832245EC5A5,false);
			ADD_POINT_TO_LIST("Ant Nest Entrance", 0x1552380D245EC5A5,false);
			ADD_POINT_TO_LIST("Manawastes", 0x15523817245EBCE1,false);
			ADD_POINT_TO_LIST("Sanctum of Desire", 0x15538814245EBCE1,false);
			ADD_POINT_TO_LIST("Temple of Sylaveth Entrance", 0x1552380F245EC5A4,false);
			ADD_POINT_TO_LIST("Syleus's Abyss Entrance", 0x15523808245EC9C4,false);
			ADD_POINT_TO_LIST("Canina Village", 0x15523836245EC6ED,false);
			ADD_POINT_TO_LIST("Grayclaw Forest", 0x15523813245EBC4D,false);
			ADD_POINT_TO_LIST("Akidu Valley", 0x15523816245EBCE1,false);
			ADD_POINT_TO_LIST("Watcher's Post", 0x1552380C245ECAF9,false);
			ADD_POINT_TO_LIST("Purelight Tower", 0x1552380E245ECAF9,false);
			ADD_POINT_TO_LIST("Purelight Hill", 0x15523805245EC9C3,false);
			ADD_POINT_TO_LIST("Ruins of Turayne", 0x15523813245EC878,false);
			ADD_POINT_TO_LIST("Shadowed Crypt Entrance", 0x1552380A245EC9C3,false);
			ADD_POINT_TO_LIST("Fonos Basin", 0x15523806245EC9C2,false);
			ADD_POINT_TO_LIST("Shattered Temple", 0x15523803245EC9C0,false);
			ADD_POINT_TO_LIST("Saurodoma Island", 0x153938132BC3720B,false);
			ADD_POINT_TO_LIST("Bercant Manor", 0x15A3380327C8657D, false);
			ADD_POINT_TO_LIST("Crimson Manor", 0x15A3380027C86598, false);
			ADD_POINT_TO_LIST("Herba Village", 0x15A3380127C865DD, false);
			ADD_POINT_TO_LIST("Forest of the Great Tree", 0x15A3381C27C86547, false);
			ADD_POINT_TO_LIST("Swamp of Silence", 0x15A3381D27C8655A, false);
			ADD_POINT_TO_LIST("Black Anvil Forge", 0x15A3380227C8656B, false);
			ADD_POINT_TO_LIST("Quietis's Demesne", 0X15A3381327C864F4, false);
	#undef ADD_POINT_TO_LIST
}

void CGameData::Update()
{
	//
	//DEBUG_INFO_OUTPUT("fs:CGameData::Update() %d \n",  PsGetCurrentThreadId());

	UpdateGlobalVars();

	//更新周围对象,,
	//DEBUG_INFO_OUTPUT("fs:CGameData::UpdateRangeActors begin\n");
	UpdateRangeActors();
	//DEBUG_INFO_OUTPUT("fs:CGameData::UpdateRangeActors end\n");

	//更新技能
	//UpdateSkill();

	//更新背包..
	//DEBUG_INFO_OUTPUT("fs:CGameData::UpdateInventory begin\n");
	//UpdateInventory();
	//DEBUG_INFO_OUTPUT("fs:CGameData::UpdateInventory end\n");

	//更新冒险，探查任务
	//std::vector<CTaskSharedPtr> tasks;
	//GetTaskAdventureExploration(tasks);

	//遍历已接委托任务数组
	//UpdateTaskDelegation();

	//更新快捷键槽
	//DEBUG_INFO_OUTPUT("fs:CGameData::UpdateQuickSlot11 begin\n");
	UpdateQuickSlot();
	//DEBUG_INFO_OUTPUT("fs:CGameData::UpdateQuickSlot end\n");

#ifdef DEBUG_MODE  
	static bool key = true;
	if (GetAsyncKeyState(VK_F1) & 0x8000 && !key)
	{



		key = true; // 设置为 true，防止重复触发
		//class CItem
		//{
		//public:
		//	UINT64 m_obj{};
		//	__int64 m_id{};
		//	unsigned char m_category{}; //类别，例如 头盔 长弓 双手剑 ...
		//	int m_count{}; //物品数量
		//	std::wstring m_name;
		//	unsigned char m_level{}; //等级
		//	unsigned char m_colour{}; //颜色品质 ， 4：稀有 3：高档 2：普通
		//	bool m_equipment{};//是否装备
		//};

		DEBUG_INFO_OUTPUT("fs:---------------------------------------------- UpdatePartyInfo ----------------------------------------------\n");
		std::vector<SPartyInfoSharedPtr> partyInfoS;
		UpdatePartyInfo(partyInfoS);
		for (auto v : partyInfoS)
		{
			DEBUG_INFO_OUTPUTW(L"fs: obj:%llx  point:%.0f , %.0f , %.0f", v->m_obj , v->m_x , v->m_y ,v->m_z);
		}

		DEBUG_INFO_OUTPUT("fs:---------------------------------------------- UpdateSchedule ----------------------------------------------\n");
		std::vector<SScheduleSharedPtr> SSchedules;
		UpdateSchedule(SSchedules);
		for (auto v : SSchedules)
		{
			DEBUG_INFO_OUTPUTW(L"fs: type:%d name:%s description%s" , v->type , v->name.c_str() , v->description.c_str());
		}

		DEBUG_INFO_OUTPUT("fs:---------------------------------------------- GetTaskAdventureExploration ----------------------------------------------\n");
		std::vector<CTaskSharedPtr> tasks;
		g_GameData.GetTaskAdventureExploration(tasks);
		for (auto v : tasks)
		{
			DEBUG_INFO_OUTPUTW(L"fs:obj:%llx id:%llx name:%s ",v->m_Obj , v->m_Id ,  v->m_Name.c_str());
			for (auto v1 : v->m_ExecutionList)
			{
				DEBUG_INFO_OUTPUTW(L"fs:   id:%llx IsComplete:%d  name:%s ", v1->Id , v1->IsComplete , v1->Describe.c_str());
			}
		}

		DEBUG_INFO_OUTPUT("fs:---------------------------------------------- GetTaskDelegation ----------------------------------------------\n");
		tasks.clear();
		g_GameData.GetTaskDelegation(tasks);
		for (auto v : tasks)
		{
			DEBUG_INFO_OUTPUTW(L"fs:obj:%llx id:%llx name:%s ", v->m_Obj, v->m_Id, v->m_Name.c_str());
			for (auto v1 : v->m_ExecutionList)
			{
				DEBUG_INFO_OUTPUTW(L"fs:   id:%llx IsComplete:%d  name:%s ", v1->Id, v1->IsComplete, v1->Describe.c_str());
			}
		}


		DEBUG_INFO_OUTPUT("fs:---------------------------------------------- UpdateInventory ----------------------------------------------\n");
		std::vector<CItemSharedPtr> items;
		UpdateInventory(items);
		for (auto value : items) {
			DEBUG_INFO_OUTPUTW(L"fs: obj: %-p m_id:%-llx  m_id2:%-10d  m_name: %-20ws\n", value->m_obj, value->m_id, value->m_id2, value->m_name.c_str());
		}

		UpdateRangeActors();
		DEBUG_INFO_OUTPUT("fs:---------------------------------------------- UpdateRangeActors ----------------------------------------------\n");
		for (auto value : m_actors) {
			DEBUG_INFO_OUTPUT("fs: obj: %-p m_id: %-10d  point:%d,%d,%d  vpoint:%d,%d,%d m_name: %-20ws\n", value->m_obj, value->m_id, (int)value->m_x , (int)value->m_y , (int)value->m_z , (int)value->m_vx , (int)value->m_vy , (int)value->m_vz, value->m_name.c_str());
		}

		DEBUG_INFO_OUTPUT("fs:---------------------------------------------- CQuickSlot ----------------------------------------------\n");
		UpdateQuickSlot();
		for (auto value : m_quickSlot) {
			DEBUG_INFO_OUTPUTW(L"fs: m_Cooling: %-d m_index: %-d m_bright: %-d m_CoolingTime: %-10d m_Resources: %-10d m_Distance: %-10d m_Name: %-20ws\n",
				value->m_cooling,
				value->m_index,
				value->m_bright,
				static_cast<int>(value->m_coolingTime),
				static_cast<int>(value->m_resources),
				static_cast<int>(value->m_distance),
				value->m_Name.c_str()
			);
		}

		//DEBUG_INFO_OUTPUT("fs:User32GetKeyState() %d \n", PsGetCurrentThreadId());



	}
	else if (GetAsyncKeyState(VK_F2) & 0x8000 && !key)
	{
		key = true; // 设置为 true，防止重复触发
		GameCore_EnumSWidgets(GameCore_SWidgetGetRoot(), [](UINT64 obj, const std::wstring& text) {

			SWidget rect{};
			GameCore_SWidgetGetRect(obj, rect);
			std::string typeName;
			GameCore_GetNameUE(GameCore_read<UINT32>(obj + 0x248), typeName);
			//DEBUG_INFO_OUTPUT("fs:typename : %s" , typeName.c_str());
			DEBUG_INFO_OUTPUTW(L"fs: widget:%llx  rect:%d , %d , %d , %d   text:%ws \n", obj, (int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height, text.c_str());
			return false;
			});
	}
	else if (GetAsyncKeyState(VK_F3) & 0x8000 && !key)
	{
		key = true; // 设置为 true，防止重复触发
		std::vector<UINT64> Objs;
		GameCore_UENameToObj("1234123411111", true, Objs);
	}
	else if (!((GetAsyncKeyState(VK_F4) & 0x8000))) {
		key = false; // 按键释放时重置标志位
	}
#endif  


}



void CGameData::SendRangeActors(WebSocketClient* pClient)
{
	// 序列化  
	msgpack::sbuffer sbuf;
	// 创建一个 packer，用于向 sbuf 中打包数据  
	msgpack::packer<msgpack::sbuffer> pk(sbuf);

	pk.pack_array(3);
	pk.pack(NetworkProtocol::AFAPI::ServerToClient::SendRangeObject);
	pk.pack(0);

	{
		std::lock_guard<std::mutex> lock(m_mutex);
		for (auto v : m_actors)
		{
			UtilUnicodeToUTF8(v->m_name, v->m_utf8name);
			UtilUnicodeToUTF8(v->m_areaName, v->m_utf8AreaName);
		}
		msgpack::pack(sbuf, m_actors);
	}


	pClient->SendBinary(sbuf.data(), sbuf.size());
}

void CGameData::SendEffects(WebSocketClient* pClient)
{
	// 序列化  
	msgpack::sbuffer m_sendbuf;
	// 创建一个 packer，用于向 sbuf 中打包数据  
	msgpack::packer<msgpack::sbuffer> packer(m_sendbuf);

	packer.pack_array(3);
	packer.pack(NetworkProtocol::AFAPI::ServerToClient::SendEffects);
	packer.pack(0);

	//std::wstring name;
	//UINT64 m_obj;
	{

		std::lock_guard<std::mutex> lock(m_mutex);

		packer.pack(m_effects);





	}

	pClient->SendBinary (m_sendbuf.data(), m_sendbuf.size());
}

void CGameData::SendQuickSlot(WebSocketClient* pClient)
{

	// 序列化  
	msgpack::sbuffer m_sendbuf;
	// 创建一个 packer，用于向 sbuf 中打包数据  
	msgpack::packer<msgpack::sbuffer> packer(m_sendbuf);

	packer.pack_array(3);
	packer.pack(NetworkProtocol::AFAPI::ServerToClient::SendQuickSlot);
	packer.pack(0);

	//std::wstring m_Name;
	//bool m_Cooling;//冷却中
	//int m_index;//快捷栏序号
	//bool m_Dim;//快捷栏是否是灰色的状态
	//float m_CoolingTime; //冷却时间
	//float m_Resources;//消耗资源
	//float m_Distance;//距离

	{
	
		std::lock_guard<std::mutex> lock(m_mutex);
		for (auto v : m_quickSlot)
		{
			UtilUnicodeToUTF8(v->m_Name, v->m_name_utf8);
		}
		packer.pack(m_quickSlot);
	}
	pClient->SendBinary(m_sendbuf.data(), m_sendbuf.size());
}

//void CGameData::SendInventory(WebSocketClient* pClient) FUNCTION_OBF_LIGHT
//{
//
//	//UINT64 m_obj;
//	//__int64 m_id;
//	//unsigned char m_category; //类别，例如 头盔 长弓 双手剑 ...
//	//int m_count; //物品数量
//	//std::wstring m_name;
//	//unsigned char m_level; //等级
//	//unsigned char m_colour; //颜色品质 ， 4：稀有 3：高档 2：普通
//	//unsigned char m_equipment;//是否装备.
//	m_sendbuf.clear();
//
//	msgpack::packer<msgpack::sbuffer> packer(m_sendbuf);
//	packer.pack_array(3);
//	packer.pack(NetworkProtocol::AFAPI::ServerToClient::SendInventory);
//	packer.pack(0);
//
//	{
//	
//		std::lock_guard<std::mutex> lock(m_mutex);
//
//		packer.pack_array(m_items.size());
//		for (const auto& item : m_items)
//		{
//			packer.pack_array(9);
//
//			packer.pack(item->m_obj);
//			packer.pack(item->m_id);
//			packer.pack(item->m_id2);
//			packer.pack(item->m_category);
//			packer.pack(item->m_count);
//			std::string name;
//			UtilUnicodeToUTF8(item->m_name, name);
//			packer.pack(name);
//			packer.pack(item->m_level);
//			packer.pack(item->m_colour);
//			packer.pack(item->m_equipment);
//
//
//
//		}
//	}
//	pClient->sendMessage(m_sendbuf.data(), m_sendbuf.size());
//}
//
void CGameData::SendTaskAdventureExploration(WebSocketClient* pClient, int requestId, const std::vector<CTaskSharedPtr>& tasks)
{
	for (auto v : tasks)
	{
		UtilUnicodeToUTF8(v->m_Name, v->m_nameutf8);
		for (auto v1 : v->m_ExecutionList)
		{
			UtilUnicodeToUTF8(v1->Describe, v1->Describeutf8);
		}
	}

	// 序列化  
	msgpack::sbuffer m_sendbuf;
	// 创建一个 packer，用于向 sbuf 中打包数据  
	msgpack::packer<msgpack::sbuffer> packer(m_sendbuf);

	packer.pack_array(4);
	packer.pack((uint32_t)NetworkProtocol::AFAPI::ServerToClient::ScriptAPISpecifyTasksResponse);
	packer.pack(requestId);
	packer.pack(0);
	packer.pack(tasks);

	pClient->SendBinary(m_sendbuf.data(), m_sendbuf.size());
}

void CGameData::SendTaskDelegation(WebSocketClient* pClient, int requestId, const std::vector<CTaskSharedPtr> &tasks)
{
	for (auto v : tasks)
	{
		UtilUnicodeToUTF8(v->m_Name, v->m_nameutf8);
		for (auto v1 : v->m_ExecutionList)
		{
			UtilUnicodeToUTF8(v1->Describe, v1->Describeutf8);
		}
	}

	// 序列化  
	msgpack::sbuffer m_sendbuf;
	// 创建一个 packer，用于向 sbuf 中打包数据  
	msgpack::packer<msgpack::sbuffer> packer(m_sendbuf);

	packer.pack_array(4);
	packer.pack((uint32_t)NetworkProtocol::AFAPI::ServerToClient::ScriptAPISpecifyTasksResponse);
	packer.pack(requestId);
	packer.pack(0);
	packer.pack(tasks);

	pClient->SendBinary(m_sendbuf.data(), m_sendbuf.size());
}

CActorSharedPtr CGameData::GetLocalPlayerActor()
{
	//std::lock_guard<std::mutex> lock(m_mutex);

	return m_LocalPlayerActor;
}

void CGameData::UpdateGlobalVars()
{
	if (!g_TLMyPc)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			UINT64 BP_TLGameInstance_C = Objs[0];
			DEBUG_INFO_OUTPUT("fs: CGameData::UpdateGlobalVars, /Engine/Transient.TLGameEngine.BP_TLGameInstance_C = %p\n", BP_TLGameInstance_C);

			g_TLMyPc = GameCore_read<UINT64, 2>(BP_TLGameInstance_C, { actorArray_offset1  , actorArray_offset2 });
			DEBUG_INFO_OUTPUT("fs: CGameData::UpdateGlobalVars, TLMyPc = %p\n", g_TLMyPc);
		}
		else
		{
			DEBUG_INFO_OUTPUT("fs: CGameData::UpdateGlobalVars, TLMyPc = %p\n", g_TLMyPc);
		}
	}

	if (!g_TLMap)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLMap").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLMap = Objs[0];
		}
	}

	if (!g_TLCodex)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLCodex").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLCodex = Objs[0];
		}
	}

	if (!g_TLTableMaster)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLTableMaster").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLTableMaster = Objs[0];
		}
	}

	if (!g_TLSkillQuickSlotObjectGroupActive)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLSkillQuickSlotObjectGroupActive").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLSkillQuickSlotObjectGroupActive = Objs[0];
		}
	}

	if (!g_TLInventory)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLInventory").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLInventory = Objs[0];
		}
	}

	if (!g_SpringArmComp)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Game/Map/ElmoredenWP/Elmoreden_P.Elmoreden_P.PersistentLevel.UnrealTLGameCameraActor.SpringArmComp").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_SpringArmComp = Objs[0];
		}
	}

	if (!g_TLTargetHelper)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLTargetHelper").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLTargetHelper = Objs[0];
		}
	}

	if (!g_TLServerManager)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLServerManager").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLServerManager = Objs[0];
		}
	}

	if (!g_TLSkillFormula)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLSkillFormula").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLSkillFormula = Objs[0];
		}
	}

	if (!g_TLTerritoryFog)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLTerritoryFog").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLTerritoryFog = Objs[0];
		}
	}

	if (!g_TLSkillSet)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLSkillSet").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLSkillSet = Objs[0];
		}
	}

	if (!g_TTLCalendar)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLCalendar").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TTLCalendar = Objs[0];
		}
	}

	if (!g_TLTimeTable)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLTimeTable").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLTimeTable = Objs[0];
		}
	}

	if (!g_TLEquip)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLEquip").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLEquip = Objs[0];
		}
	}

	if (!g_TLGameModeController)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLGameModeController").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLGameModeController = Objs[0];
		}
	}

	if (!g_TLParty)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLParty").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLParty = Objs[0];
		}
	}
	
	if (!g_TLMapIcon)
	{
		std::vector<UINT64> Objs;
		GameCore_UENameToObj(skCrypt("/Engine/Transient.TLGameEngine.BP_TLGameInstance_C.TLMapIcon").decrypt(), false, Objs);
		if (Objs.size() > 0)
		{
			g_TLMapIcon = Objs[0];
		}
	}
	
	
}
// rotate left
template<class T> T __ROL__(T value, int count)
{
	const UINT nbits = sizeof(T) * 8;

	if (count > 0)
	{
		count %= nbits;
		T high = value >> (nbits - count);
		if (T(-1) < 0) // signed value
			high &= ~((T(-1) << count));
		value <<= count;
		value |= high;
	}
	else
	{
		count = -count % nbits;
		T low = value << (nbits - count);
		value >>= count;
		value |= low;
	}
	return value;
}
inline UINT64 __ROR8__(UINT64 value, int count) { return __ROL__((UINT64)value, -count); }
void CGameData::UpdateRangeActors()
{
	if (!g_TLMyPc)
	{
		return;
	}
	std::vector<CActorSharedPtr> actors;

	auto temp = GameCore_read<UINT64>(g_TLMyPc + fs_movToPoint_rcx + 0x8);
	if (!temp) return;
	temp = GameCore_read<UINT64>(temp + 0xc8);
	if (!temp) return;
	auto begin = GameCore_read<UINT64>(temp + 0x20);
	if (!begin) return;
	int size = GameCore_read<int>(temp + 0x28);

	for (int i = 0; i < size; i++)
	{
		UINT64 obj = GameCore_read<UINT64>(begin + i * 8);
		if (obj)
		{
			auto actor = std::make_shared<CActor>();//new CActor;

			actor->m_obj = obj;

			//取坐标 , 在内存中坐标顺序是 x , z ,y 
			TLPoint r(0, 0, 0);
			if (GameCore_GetObjPoint(obj  , &r))
			{
				actor->m_vx = r.x;
				actor->m_vy = r.y;
				actor->m_vz = r.z;

				GameCore_PointVToR(&r);
				actor->m_x = r.x;
				actor->m_y = r.y;
				actor->m_z = r.z;

			}

			//取对象名字
			UINT64 tempObj = GameCore_read<UINT64>(obj + ActorNameOff);
			//DEBUG_INFO_OUTPUT("fs: obj:%llx   tempObj:%llx", obj, tempObj);
			if (tempObj)
			{

				GameCore_UEGetText(tempObj, actor->m_name);
				//DEBUG_INFO_OUTPUTW(L"fs:%s", actor->m_name.c_str());

			}
			
			//是否是玩家
			actor->m_isPlayer = GameCore_IsPlayer(obj);

			//取血，蓝，是否敌对
			actor->m_isAttackable = GameCore_IsObjectAttackable(actor->m_obj);

			UINT64 hpObj = GameCore_read<UINT64>(obj + hpObj_OFF);
			if (hpObj)
			{
				//UINT64 attributeListBegin = GameCore_read<UINT64>(GameCore_GetGameBaseAddress() + attributeListBase);
				//UINT64 index = hpObj xor hpOffencrypt;
				//hpObj = GameCore_read< UINT64>(8 * index + attributeListBegin);
				hpObj = __ROR8__(hpObj, 0x1B) ^ hpOffencrypt;

				if (hpObj)
				{
					//hpObj = hpObj xor hpOffencrypt1;

					actor->m_hpMax = GameCore_read<float>(hpObj + 0x48);
					*((DWORD32*)(&(actor->m_hp))) = GameCore_read<DWORD32>(hpObj + 0x54) xor hpOffencrypt1;
					//DEBUG_INFO_OUTPUT("fs:UpdateRangeActors  %ws hp:%d/%d %p\n", actor->m_name.c_str(), (int)(actor->m_hp) , (int)(actor->m_hpMax), hpObj);

				}
			}
			UINT64 mpObj = GameCore_read<UINT64>(obj + mpObj_OFF);
			if (mpObj)
			{
				actor->m_mp = GameCore_read<float>(mpObj + 0x18);
				actor->m_mpMax = GameCore_read<float>(mpObj + 0x18 + 4);
			}

			//
			actor->m_isAlive = GameCore_IsObjectAlive(actor->m_obj);
			actor->m_id = GameCore_read<int>(obj + ActorIDOff);

			//当前施法技能ID2
			UINT64 skillObj = GameCore_read<UINT64>(actor->m_obj + isCastOffset);
			if (skillObj)
			{
				skillObj = skillObj xor CastSkillObjEncrypt;
				actor->m_castID = GameCore_read<UINT32>(skillObj + 0x10);
				UINT64 skillTemp = GameCore_read<UINT64>(actor->m_obj + monster_skill_release_1);
				if (skillTemp)
				{
					//DEBUG_INFO_OUTPUT("fs: UpdateRangeActors m_skillAttackSpeed : %d  skillObj:%llx obj:%llx\n", (int)GameCore_read<float>(skillTemp + skillAttackSpeed_OFF), skillObj , actor->m_obj);
					m_skillAttackSpeed[actor->m_castID] = GameCore_read<float>(skillTemp + skillAttackSpeed_OFF);
				}

			}

			//怪物当前仇恨对象
			actor->m_targetID = GameCore_read<UINT64, 2>(actor->m_obj, { monster_hate1 , monster_hate2 });

			GameCore_GetAttackInfo(actor->m_obj , m_skillAttackSpeed , actor->m_attackInfo);

			//更新效果数组
			{
				for (size_t i = 0; i < 8; i++)
				{
					UINT64 temp = GameCore_read<UINT64 >(actor->m_obj + EffectArrayOFF) + EffectArrayOFF1 + i * 0x10;
					UINT64 begin = GameCore_read<UINT64>(temp);
					UINT64 length = GameCore_read<UINT32>(temp + 0x8);
					//DEBUG_INFO_OUTPUT("fs: UpdateRangeActors begin:%llx length:%llx \n", begin , length);
					if (!IsReadPtr(begin))
					{
						continue;
					}
					for (size_t j = 0; j < length; j++)
					{
						UINT64 node = GameCore_read<UINT64>(begin + j * 8);
						UINT64 obj = GameCore_read<UINT64>(node + EffectObjOFF);
						if (IsReadPtr(obj))
						{
							BYTE b = GameCore_read<BYTE, 3>(obj, { EffectObjOFF1 , EffectObjOFF2 , EffectObjOFF3 });
							if (b)
							{
								auto effectObj = std::make_shared<SEffect>();
								unsigned int nameID = GameCore_read<unsigned int>(obj + 0x8);
								//DEBUG_INFO_OUTPUT("fs: UpdateRangeActors obj:%p  \n", obj);
								if (nameID)
								{
									GameCore_GetNameUE(nameID, effectObj->name);
								}
								//DEBUG_INFO_OUTPUT("fs: UpdateRangeActors %s \n", effectObj->name.c_str());
								actor->m_Effects.push_back(effectObj);
							}

						}
					}
				}
			}

			actors.emplace_back(actor);
		}
	}

	//更新本地玩家信息
	UpdateActorsInternal(actors);

	//The vector is swapped here.
	{
	
		std::lock_guard<std::mutex> lock(m_mutex);
		m_actors = actors;

	}
}

void CGameData::UpdateActorsInternal(std::vector<CActorSharedPtr>& actors)
{
	for (auto actor : actors)
	{
		if (actor->m_obj == GameCore_read<UINT64>(g_TLMyPc + playerObjOffset))
		{

			UpdateActorEffect(actor->m_Effects);

			auto obj = actor->m_obj;
			actor->m_LocalPlayers = true;
			//m_LocalPlayerActor->m_selectID = read<int>(getTLTargetHelper() + 选择对象_OFFSET);
			//m_LocalPlayerActor->m_selectID = m_LocalPlayerActor->m_selectID == -1 ? 0 : m_LocalPlayerActor->m_selectID;
			actor->m_isMove = GameCore_read<bool>(g_TLMyPc + isMove_OFF);
			//ctx->g_PlayerInfo->m_worldMessageCharacterId = read<UINT64>(m_LocalPlayerActor->m_obj + worldMessageCharacterId);
			//取等级
			actor->m_level = GameCore_read<UINT32, 3>(actor->m_obj, { 0x8 , 0xc0 , levelOffset });
			//PrintA("fs: 等级:%d" , m_LocalPlayerActor->m_level);

			//取当前是否在剧情动画..
			//auto temp = GameCore_read<UINT64>(GameCore_GetGameBaseAddress() + donghuaBase_BASE);
			//if (temp)
			//{
			actor->m_isAnimation = GameCore_read<bool>(GameCore_GetGameBaseAddress() + donghuaBase_BASE + story_animation_offset);
			//}

			//更新深渊与副本点数
			{

				actor->m_abyssPoint = GameCore_read<int, 3>(GameCore_GetGameBaseAddress() + abyssPoint_BASE, { 0 , 0x8 , 0x7c });
				actor->m_PartyDungeonPoint = GameCore_read<int, 3>(GameCore_GetGameBaseAddress() + PartyDungeonPoint_BASE, { 0 , 0x8 , 0xe8 });
				actor->m_ContractPoint = GameCore_read<int, 3>(GameCore_GetGameBaseAddress() + ContractPoint_BASE, { 0 , 0x8 , ContractPoint_OFF });
				

			}

			//判断是否在副本
			actor->m_isDungeon = GameCore_IsDungeon();

			//更新天气
			UINT32 v1 = GameCore_read<UINT32>(g_TTLCalendar + isDaytimeOFF + 0x8);
			if (v1 >= 0x12 || v1 <= 1)
			{
				actor->m_isDaytime = false;
			}
			else
			{
				actor->m_isDaytime = true;
			}


			//更新金币
			actor->m_gold = GetCurrency(0);
			//DEBUG_INFO_OUTPUT("fs:m_gold:%llx m_isDaytime:%d\n", actor->m_gold, actor->m_isDaytime);


			//取人物属性
			actor->m_statPoints = GameCore_read<int, 3>(actor->m_obj, { 0x8 , 0xc0 , statPointsOFF });//属性点
			actor->m_strength = GameCore_read<int, 3>(actor->m_obj, { 0x8 , 0xc0 , statPointsOFF + 0x8 });//斗志
			actor->m_dexterity = GameCore_read<int, 3>(actor->m_obj, { 0x8 , 0xc0 , statPointsOFF + 0xc });//中气
			actor->m_wisdom = GameCore_read<int, 3>(actor->m_obj, { 0x8 , 0xc0 , statPointsOFF + 0x10 });//智慧
			actor->m_perception = GameCore_read<int, 3>(actor->m_obj, { 0x8 , 0xc0 , statPointsOFF + 0x14 });//洞察

			//取武器序号

			if (g_TLMap)
			{
				if (GameCore_read<UINT64>(g_TLMap + current_map_area_name))
				{
					if (GameCore_UEGetText(GameCore_read<UINT64, 2>(g_TLMap + current_map_area_name, { 0 , 0x8 }), actor->m_areaName))
					{


					}
				}
			}

			//取人物体能
			actor->m_stamina = GameCore_read<float>(g_TLMyPc + physical_fitness);

			actor->m_weaponIndex = GameCore_read<bool, 2>(obj + weaponIndexOffset, { 0 , weaponIndexOffset1 });
			actor->m_isLocal = true;

			m_LocalPlayerActor = actor;

			//FIXED: break here, since there should be only one localplayer
			break;
		}

		//actor->m_distance = CActor::getDistance(ctx->m_LocalPlayerActor, actor);
	}

	if (m_LocalPlayerActor)
	{
		for (const auto& actor : actors)
		{
			actor->m_distance = GameCore_GetObjectDistance(m_LocalPlayerActor.get(), actor.get());
		}
	}
}

void CGameData::UpdateSkill(std::vector<CSkillSharedPtr>& skills)
{
	//DEBUG_INFO_OUTPUT("fs: ---------------------- skill ------------------------");
	UINT64 temp = GameCore_read<UINT64, 4>(g_TLMyPc, { skillArray_offset , 8 , 8 , 0xe8 });
	if (temp)
	{
		UINT64 begin = GameCore_read<UINT64>(temp + skillArrayOffset);
		UINT32 size = GameCore_read<UINT64>(temp + skillArrayOffset + 0x8);
		for (UINT32 i = 0; i < size; i++)
		{

			UINT64 node = begin + i * 0x20;
			auto skill = std::make_shared<CSkill>();

			skill->m_obj = GameCore_read<UINT64>(node + 0x8);
			skill->m_id1 = GameCore_read<UINT32>(node);
			skill->m_id2 = GameCore_read<UINT32, 2>(skill->m_obj + skillAttributeOffset, { 0 , 0x10 });

			//取技能等级
			UINT64 AttributeObj = SkillID1ToAttribute(skill->m_id1);
			if (AttributeObj)
			{
				skill->m_level = GetSkillLevel(AttributeObj);
			}

			//取技能名
			UINT64 nameObj = GameCore_read<UINT64, 3>(skill->m_obj, { skillAttributeOffset  , skillNameOffset , skillNameOffset2 });
			if (nameObj)
			{
				GameCore_UEGetText(nameObj, skill->m_name);
			}
			//DEBUG_INFO_OUTPUT("fs: UpdateSkill obj:%llx  m_id1:%x m_id2:%x m_level:%llx  %ws\n",
			//	skill->m_obj,
			//	skill->m_id1,
			//	skill->m_id2,
			//	skill->m_level,
			//	skill->m_name.c_str()
			//);

			skills.push_back(skill);
		}
	}
}

void CGameData::UpdateInventory(std::vector<CItemSharedPtr>& items)
{
	if (!g_TLInventory)
	{
		return;
	}

	UINT64 begin = GameCore_read<UINT64>(g_TLInventory + Inventory_off1 + Inventory_begin);
	int count = GameCore_read<int>(g_TLInventory + Inventory_off1 + Inventory_begin + 0x8);

	if (!begin || count > 0xfff)
	{
		return;
	}

	for (int i = 0; i < count; i++)
	{
		UINT64 obj = GameCore_read<UINT64>(begin + i * 0x20 + 0x8);
		if (obj)
		{

			auto item = std::make_shared<CItem>();
			item->m_obj = obj;
			UINT64 FieldObj = GameCore_read<UINT64>(obj + itemFieldOffset_1);

			if (!FieldObj)
			{
				continue;
			}

			item->m_id2 = GameCore_read<int, 2>(FieldObj, { 0x138 , 0x20 });

			//DEBUG_INFO_OUTPUT("fs: UpdateInventory FieldObj:%llx" , FieldObj);

			//取物品名	
			UINT64 nameObj = GameCore_ItemToNameObj(FieldObj);
			if (nameObj)
			{
				nameObj = GameCore_read<UINT64>(nameObj + itemNameOffset);
				if (nameObj)
				{
					GameCore_UEGetText(nameObj, item->m_name);
				}

			}
			//取物品ID
			item->m_id = GameCore_read<UINT64>(begin + i * 0x20);

			//取物品数量
			item->m_count = GameCore_read<int>(obj + 0x60);

			//取物品类别
			item->m_category = GameCore_read<BYTE>(FieldObj + itemCategoryOffset);

			//取物品品质
			item->m_colour = GameCore_read<BYTE>(FieldObj + itemColourOffset);

			//取物品等级
			item->m_level = GameCore_read<BYTE>(obj + itemLevelOffset);

			//物品是否装备上
			item->m_equipment = GameCore_read<bool>(obj + itemIsEquipmentOffset);
			//DEBUG_INFO_OUTPUT("fs: UpdateInventory obj:%llx  id:%llx  name:%ws m_equipment:%d\n",
			//	item->m_obj,
			//	item->m_id,
			//	item->m_name.c_str() ,
			//	item->m_equipment
			//);
			items.push_back(item);
		}
	}


}

void CGameData::GetTaskAdventureExploration(std::vector<CTaskSharedPtr>& tasks)
{

	UINT64 Codex = GameCore_read<UINT64>(g_TLTableMaster + CodexOffset);

	//DEBUG_INFO_OUTPUT("fs: GetTaskAdventureExploration begin %p %p\n", g_TLTableMaster, Codex);

	if (!Codex)
	{
		return;
	}

	UINT64 begin = GameCore_read<UINT64>(Codex + 0x138);
	UINT32 length = GameCore_read<DWORD32>(Codex + 0x140);

	if (!begin || length > 0xfff)
	{
		return;
	}
	std::vector<CTaskSharedPtr> taskAdventureExploration;

	for (UINT32 i = 0; i < length; i++)
	{
		//DEBUG_INFO_OUTPUT("fs: UpdateTaskAdventureExploration 2\n");
		UINT64 id = GameCore_read<UINT64>(begin + i * 0x18);
		//auto taskIdToObj = (UINT64(__fastcall*)(UINT64 Codex, UINT64 * output, UINT64 id))(GetCurrentModuleBaseAddress() + fs_taskIdToObj_CALL);
		//if (IsBadReadPtr((const void*)(taskIdToObj), 8))
		//{
		//	break;
		//}
		UINT64 taskObj = GameCore_read<UINT64>(begin + i * 0x18 + 0x8);

		//taskIdToObj(Codex, &taskObj, id);
		if (taskObj)
		{
			auto task = std::make_shared<CTask>();

			task->m_Obj = taskObj;
			task->m_Id = id;

			//取任务名
			UINT64 nameObj = GameCore_read<UINT64, 2>(taskObj, { 0x48 , 0x8 });
			if (nameObj)
			{
				//DEBUG_INFO_OUTPUT("fs: UpdateTaskAdventureExploration 3\n");
				GameCore_UEGetText(nameObj, task->m_Name);
				//DEBUG_INFO_OUTPUT("fs: UpdateTaskAdventureExploration 4\n");
				//DEBUG_INFO_OUTPUT("fs: UpdateTaskAdventureExploration + id:%-16llx  taskObj:%-16llx  %-20ws\n" , id, taskObj, task->m_Name.c_str());
			}


			//遍历子进度..
			UINT64 textBegin = GameCore_read<UINT64>(taskObj + 0x38);
			if (!textBegin)
			{
				break;
			}
			UINT32 textBeginSize = GameCore_read<UINT32>(taskObj + 0x40);
			UINT64 attributeBegin = GameCore_read<UINT64>(taskObj + task_object_attribute_array);
			if (!attributeBegin || textBeginSize > 0xff)
			{
				break;
			}
			UINT64 attributeBeginSize = GameCore_read<UINT32>(taskObj + task_object_attribute_array + 0x8);

			//DEBUG_INFO_OUTPUT("fs: -------------start--------------\n");
			//DEBUG_INFO_OUTPUT("fs: UpdateTaskAdventureExploration + id:%-16llx  taskObj:%-16llx  %-20ws  textBeginSize:%d\n", id, taskObj, task->m_Name.c_str(), textBeginSize);

			//textBegin数组和attributeBegin大小是一样的，所以放一起遍历
			for (size_t subIndex = 0; subIndex < textBeginSize; subIndex++)
			{

				UINT64 attributeNode = GameCore_read<UINT64>(attributeBegin + subIndex * 8);
				UINT64 textNode = textBegin + subIndex * task_description_text_array_structure;

				auto subExecution = std::make_shared<SExecution>();
				//遍历格式化文本的参数
				if (textNode)
				{
					//DEBUG_INFO_OUTPUT("fs: UpdateTaskAdventureExploration 5\n");
					GameCore_DescriptionTextFormatting(textNode, subExecution->Describe);
					//DEBUG_INFO_OUTPUT("fs: UpdateTaskAdventureExploration 6\n");

				}

				if (attributeNode)
				{

					//判断任务是否完成
					subExecution->Id = GameCore_read<UINT64>(attributeNode);
					//DEBUG_INFO_OUTPUT("fs: UpdateTaskAdventureExploration 7\n");
					subExecution->IsComplete = GameCore_TaskIsComplete(subExecution->Id);
					//DEBUG_INFO_OUTPUT("fs: UpdateTaskAdventureExploration 8\n");

				}
				task->m_ExecutionList.push_back(subExecution);
				//DEBUG_INFO_OUTPUT("fs: UpdateTaskAdventureExploration IsComplete:%d DescribeText:%ws\n", subExecution->IsComplete, subExecution->Describe.c_str());
			}
			//DEBUG_INFO_OUTPUT("fs: -------------end--------------\n");
			tasks.push_back(task);
		}
	}

	//DEBUG_INFO_OUTPUT("fs: UpdateTaskAdventureExploration end\n");
}

void CGameData::GetTaskDelegation(std::vector<CTaskSharedPtr>& tasks)
{
	UINT64 temp = GameCore_read<UINT64, 2>(GameCore_GetGameBaseAddress(), { DelegateTask_BASE , 0x8 }) + DelegateTaskOFF1;
	UINT64 begin = GameCore_read<UINT64>(temp);
	UINT32 beginLen = GameCore_read<UINT32>(temp + 0x8);


	for (UINT64 i = 0; i < beginLen; i++)
	{
		UINT64 node = begin + i * 0x20;
		UINT64 obj = GameCore_read<UINT64>(node + 0x8);
		if (obj)
		{
			auto taskObj = std::make_shared<CTask>();
			taskObj->m_Id = GameCore_read<__int64>(node);
			if (taskObj->m_Id < 0)
			{
				continue;
			}

			//取任务名

			UINT64 taskStruct = GameCore_DelegateTaskGetStruct(taskObj->m_Id);
			if (!taskStruct)
			{
				continue;

			}
			DEBUG_INFO_OUTPUT("fs: taskStruct:%llx" , taskStruct);
			UINT64 nameObj = GameCore_read<UINT64, 2>(taskStruct, { 0xa8 , 0x8 });
			if (nameObj)
			{
				GameCore_UEGetText(nameObj, taskObj->m_Name);
			}

			//DEBUG_INFO_OUTPUT("fs: GetTaskDelegation ---------------------------start \n");
			//DEBUG_INFO_OUTPUT("fs: GetTaskDelegation:%llx %ws \n", obj, taskObj->m_Name.c_str());

			//遍历进度列表

			UINT64 jinduBegin = GameCore_read<UINT64>(obj + SExecutionTextOFF1);
			if (!jinduBegin)
			{
				continue;
			}
			UINT32 jinduBeginSize = GameCore_read<UINT32>(obj + SExecutionTextOFF1 + 0x8);
			for (UINT64 subIndex = 0; subIndex < jinduBeginSize; subIndex++)
			{
				auto ExecutionObj = std::make_shared<SExecution>();
				UINT64 node = jinduBegin + subIndex * 0x20;
				UINT64 jinduObj = GameCore_read<UINT64>(node + 0x8);
				ExecutionObj->Id = GameCore_read<UINT64>(node);
				if (!jinduObj)
				{
					continue;
				}
				ExecutionObj->Count = GameCore_read<int>(jinduObj + 0x84);
				ExecutionObj->MaxCount = GameCore_read<int>(jinduObj + 0x80);

				GameCore_DelegateDescriptionTextFormatting(jinduObj, ExecutionObj->Describe);

				//DEBUG_INFO_OUTPUT("fs: GetTaskDelegation ID:%llx Describe : %ws \n", ExecutionObj->Id, ExecutionObj->Describe.c_str());
				taskObj->m_ExecutionList.push_back(ExecutionObj);
			}

			tasks.push_back(taskObj);
		}
	}
}

void CGameData::UpdateQuickSlot()
{
	UINT64 begin = GameCore_read<UINT64>(g_TLSkillQuickSlotObjectGroupActive + 0x50);
	UINT32 size = GameCore_read<UINT32>(g_TLSkillQuickSlotObjectGroupActive + 0x58);

	if (!begin)
	{
		return;
	}

	std::vector<CQuickSlotSharedPtr> quickSlots;
	for (UINT32 i = 0; i < size; i++)
	{
		auto slot = std::make_shared<CQuickSlot>();
		UINT64 infoPtr = GameCore_read<UINT64>(begin + i * 8);

		if (!infoPtr)
		{
			continue;
		}

		UINT64 skillAttributePtr = GameCore_read<UINT64>(infoPtr + SkillBarStructure);
		//取技能名
		UINT64 nameObj = GameCore_read<UINT64>(infoPtr + QuickSlotNameOff);
		if (nameObj)
		{
			GameCore_UEGetText(nameObj, slot->m_Name);
		}
		if (skillAttributePtr)
		{
			slot->m_cooling = GameCore_IsSkillCooldown(skillAttributePtr);

			UINT32 attribute = GameCore_read<UINT32>(skillAttributePtr + 0x20);//这个 0x20  大更会变，请注意
			if (attribute)
			{
				UINT64 attributeObj = GameCore_SkillGetAttribute(attribute);
				//DEBUG_INFO_OUTPUT("fs: UpdateQuickSlot infoPtr:%llx attributeObj:%llx\n", infoPtr , attributeObj);
				if (attributeObj)
				{
					slot->m_coolingTime = GameCore_read<float>(attributeObj + SkillResourceConsumptionOffset + 0x8);
					slot->m_resources = GameCore_read<float>(attributeObj + SkillResourceConsumptionOffset);
					slot->m_distance = GameCore_read<float>(attributeObj + 0x8) / 100;
				}

			}

		}
		slot->m_bright = GameCore_read<bool>(infoPtr + DimOFFSET);
		slot->m_index = GameCore_read<int>(infoPtr + 0x60);


		quickSlots.push_back(slot);
	}

	{
		std::lock_guard<std::mutex> lock(m_mutex);
		m_quickSlot = quickSlots;
	}

}

void CGameData::UpdateActorEffect(std::vector<SEffectSharedPtr>& Effect)
{

	UINT64 temp = GameCore_read<UINT64>(GameCore_GetGameBaseAddress() + effectBase);
	if (!temp)
	{
		return;
	}

	temp = GameCore_read<UINT64>(temp + 0x8);
	if (!temp)
	{
		return;
	}

	temp = GameCore_read<UINT64>(temp + effectOffset);

	if (!temp)
	{
		return;
	}

	UINT64 linkBegin = GameCore_read<UINT64>(temp + 0x58);
	UINT32 linkSize = GameCore_read<UINT64>(temp + 0x68);

	if (!linkSize)
	{
		return;
	}

	while (linkBegin)
	{
		UINT64 obj = GameCore_read<UINT64>(linkBegin + 0x60);
		if (obj)
		{
			auto effectObj = std::make_shared<SEffect>();
			Effect.push_back(effectObj);
			effectObj->m_obj = obj;

			unsigned int nameID = GameCore_read<unsigned int>(obj + 0x8);
			//DEBUG_INFO_OUTPUT("fs: UpdateActorEffect obj:%p  \n", obj);
			if (nameID)
			{
				GameCore_GetNameUE(nameID, effectObj->name);
			}
		}
		linkBegin = GameCore_read<UINT64>(linkBegin + EffectLinkedListOffset);
	}
}

void CGameData::UpdateSWidget()
{

}

void CGameData::UpdateTeleportPoint(std::vector<STeleportPointSharedPtr>& TeleportPoints)
{
	for (const auto& p : m_teleports)
	{
		auto TeleportPointObj = std::make_shared<STeleportPoint>();
		TeleportPointObj->id = p->id;
		TeleportPointObj->name = p->name;
		TeleportPointObj->isOpen = IsTeleportPointOpen(p->id);
		//DEBUG_INFO_OUTPUT("fs: UpdateTeleportPoint isOpen: %d %s \n" , TeleportPointObj->isOpen , TeleportPointObj->name.c_str());
		TeleportPoints.push_back(TeleportPointObj);
	}
}

void CGameData::UpdateSchedule(std::vector<SScheduleSharedPtr>& SSchedules)
{
	if (!g_TLTimeTable)
	{
		return;
	}
	UINT64 begin = GameCore_read<UINT64>(g_TLTimeTable + ScheduleArray);
	UINT64 size = GameCore_read<UINT32>(g_TLTimeTable + ScheduleArray + 0x8);
	//DEBUG_INFO_OUTPUT("fs: begin:%llx  \n", g_TLTimeTable + 0x98);
	if (!begin)
	{
		return ;
	}
	for (size_t i = 0; i < size; i++)
	{
		UINT64 infoAdd = begin + i * 0x10;
		UINT64 id = GameCore_read<UINT64>(infoAdd);
		BYTE type = GameCore_read<BYTE>(infoAdd + 0xa);
		if (!id)
		{
			continue;
		}
		UINT64 info = GetScheduleInfo(id);
		if (!info)
		{
			continue;
		}

		auto SScheduleObj = std::make_shared<SSchedule>();
		SScheduleObj->type = type;

		UINT64 nameObj{};
		UINT64 descriptionObj{};
		if ((unsigned __int8)(type - 1) <= 1u || type >= 6u)
		{
			if (type == 1)
			{
				descriptionObj = GameCore_read<UINT64>(info + ScheduletextOffset1);
				nameObj = GameCore_read<UINT64>(info + ScheduletextOffset2);
			}
			else
			{
				if (type != 2)
					break;
				descriptionObj = GameCore_read<UINT64>(info + ScheduletextOffset3);
				nameObj = GameCore_read<UINT64>(info + ScheduletextOffset4);
			}
		}
		else
		{
			descriptionObj = GameCore_read<UINT64>(info + ScheduletextOffset5);
			nameObj = GameCore_read<UINT64>(info + ScheduletextOffset6);
		}
		if (nameObj)
		{
			GameCore_UEGetText(nameObj, SScheduleObj->name);
		}
		if (descriptionObj)
		{
			GameCore_UEGetText(descriptionObj, SScheduleObj->description);
		}

		SSchedules.push_back(SScheduleObj);
		//DEBUG_INFO_OUTPUT("fs: nameObj:%llx  descriptionObj:%llx" , nameObj , descriptionObj);
		//DEBUG_INFO_OUTPUT("fs: id:%llx  type:%d  info:%llx  name:%ws   description:%ws\n" , id , type , info , SScheduleObj->name.c_str() , SScheduleObj->description.c_str());
	}
}

void CGameData::UpdatePartyInfo(std::vector<SPartyInfoSharedPtr>& partyInfoS)
{
	if (!g_TLParty)
		return;
	size_t begin = GameCore_read<UINT64>(g_TLParty + 0x80);
	size_t size = GameCore_read<int>(g_TLParty + 0x80 + 0x8);

	if (!begin)
		return;

	for (size_t i = 0; i < size; i++)
	{
		size_t PartyObj = GameCore_read<UINT64>(begin + i * 0x10);
		if (!PartyObj)
			continue;

		auto SScheduleObj = std::make_shared<SPartyInfo>();
		SScheduleObj->m_obj = PartyObj;
		auto point_id = GameCore_read<UINT64>(PartyObj + 0x40);
		if (point_id)
		{
			auto point = GameCore_PartyGetStructById(point_id);
			if (point)
			{
				point += 0x28;
				SScheduleObj->m_x = *((float*)(point));
				SScheduleObj->m_y = *((float*)(point + 0x4));
				SScheduleObj->m_z = *((float*)(point + 0x8));
			}
		}

		auto nameObj = GameCore_read<UINT64>(PartyObj + 0x48);
		if (nameObj)
		{
			GameCore_UEGetText(nameObj, SScheduleObj->m_name);
			UtilUnicodeToUTF8(SScheduleObj->m_name, SScheduleObj->m_name_utf8);
		}

		SScheduleObj->m_level = GameCore_read<int>(PartyObj + 0x68);
		SScheduleObj->m_hp = GameCore_read<int>(PartyObj + 0x6c);
		SScheduleObj->m_hpMax = GameCore_read<int>(PartyObj + 0x70);
		SScheduleObj->m_mp = GameCore_read<int>(PartyObj + 0x74);
		SScheduleObj->m_mpMax = GameCore_read<int>(PartyObj + 0x78);
		SScheduleObj->m_dungeonID = GameCore_read<int>(PartyObj + 0x98);
		SScheduleObj->m_isCaptain = GameCore_read<bool>(PartyObj + 0xf3);
		partyInfoS.push_back(SScheduleObj);
		
	}
}

TaskCall* CGameData::GetCall()
{
	if (m_MainCall == NULL)
	{
		return NULL;
	}
	TaskCall* call = NULL;
	{
		std::lock_guard<std::mutex> lock(m_mutex_call);
		call = m_MainCall;
		m_MainCall = NULL;
	}
	return call;
}

void CGameData::AddCall(TaskCall* call)
{
	std::lock_guard<std::mutex> lock(m_mutex_call);
	m_MainCall = call;
}
